package com.moqianfan.mcuassistant.activity;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.LinearInterpolator;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

import com.moqianfan.mcuassistant.R;
import com.moqianfan.mcuassistant.adapter.CommDataAdapter;
import com.moqianfan.mcuassistant.bean.BlueValue;
import com.moqianfan.mcuassistant.comm.Common;
import com.moqianfan.mcuassistant.utils.LogUtil;
import com.moqianfan.mcuassistant.view.LineGridView;
import com.moqianfan.mcuassistant.view.ListDialog;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * Created by Administrator on 2016/12/10.
 * 蓝牙助手
 */

public class BlueToothActivity extends AppCompatActivity implements View.OnClickListener,
        AdapterView.OnItemClickListener, SeekBar.OnSeekBarChangeListener, AdapterView.OnItemLongClickListener {

    private BluetoothReceiver receiver;
    private BluetoothAdapter bluetoothAdapter;
    private String address;//选中的蓝牙地址
    private String name;//选中的蓝牙名称
    private List<String> devices;
    private List<BluetoothDevice> deviceList;
    private ArrayList<BlueValue> mValues;

    private ConnectedThread connectedThread;

    private CommDataAdapter<BlueValue> dataAdapter;//搜索列表适配器
    private CommDataAdapter<BlueValue> mBlueValueAdapter;//搜索列表适配器
    private ArrayList<BlueValue> datas;//搜索列表
    private ListDialog dialog, editDialog;//搜索对话框


    //请求代码
    private static final int REQUEST_ENABLE_BT = 2;

    private ImageView imageBack, imageRotate;
    private TextView txtConnStatus;
    private ListView listView;
    private TextView txtDiscover;
    private SeekBar mSeekBarP, mSeekBarI, mSeekBarD;
    private TextView txtSeekP, txtSeekI, txtSeekD;
    private LineGridView mGridView;

    //旋转动画配置
    private Animation operatingAnim;

    private String[] saveValue = {"key0", "key1", "key2", "key3", "key4", "key5", "key6",
            "key7", "key8", "key9", "key10", "key11"};
    private final static String TAG = "BlueToothActivity";

    private SharedPreferences mPreferences;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_blue);
        imageBack = (ImageView) findViewById(R.id.image_back);
        imageRotate = (ImageView) findViewById(R.id.image_rotate);
        txtConnStatus = (TextView) findViewById(R.id.txt_conn_status);
        txtDiscover = (TextView) findViewById(R.id.txt_discover);
        mSeekBarP = (SeekBar) findViewById(R.id.seek_p);
        mSeekBarI = (SeekBar) findViewById(R.id.seek_i);
        mSeekBarD = (SeekBar) findViewById(R.id.seek_d);
        txtSeekP = (TextView) findViewById(R.id.txt_seek_pvalue);
        txtSeekI = (TextView) findViewById(R.id.txt_seek_ivalue);
        txtSeekD = (TextView) findViewById(R.id.txt_seek_dvalue);
        mGridView = (LineGridView) findViewById(R.id.grad_key_value);
        initViews();
    }

    private void initViews() {
        mPreferences = getSharedPreferences("blueValue", MODE_PRIVATE);
        imageBack.setOnClickListener(this);
        txtDiscover.setOnClickListener(this);
        mSeekBarP.setOnSeekBarChangeListener(this);
        mSeekBarI.setOnSeekBarChangeListener(this);
        mSeekBarD.setOnSeekBarChangeListener(this);

        deviceList = new ArrayList<>();
        devices = new ArrayList<>();
        datas = new ArrayList<>();
        mValues = new ArrayList<>();

        String value;
        for (int i = 0; i < 12; i++) {
            value = mPreferences.getString("key" + i, null);
            if (null != value) {
                mValues.add(new BlueValue(value.split("=")[0], value.split("=")[1]));
            } else {
                mValues.add(new BlueValue("按键" + i, "" + i));
            }
        }
        if (null == mBlueValueAdapter) {

            mBlueValueAdapter = new CommDataAdapter<BlueValue>(mValues, R.layout.view_item_blue_grid) {
                @Override
                public void bindView(ViewHolder holder, BlueValue obj) {
                    holder.setText(R.id.txt_blue_key, obj.getKey());
                }
            };
            mGridView.setAdapter(mBlueValueAdapter);
        } else {
            mBlueValueAdapter.setmData(mValues);
        }
        mGridView.setOnItemClickListener(this);
        mGridView.setOnItemLongClickListener(this);

        IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
        receiver = new BluetoothReceiver();
        registerReceiver(receiver, filter);
        filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        registerReceiver(receiver, filter);
        filter = new IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED);
        registerReceiver(receiver, filter);
        filter = new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED);
        registerReceiver(receiver, filter);
        filter = new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
        registerReceiver(receiver, filter);
        if (null == dialog) {
            dialog = new ListDialog(this);
            dialog.setCanceledOnTouchOutside(false);
            dialog.setContentView(R.layout.view_discovery_blue_dialog);
            listView = (ListView) dialog.findViewById(R.id.list_dis);
            listView.setOnItemClickListener(this);
        }
        //保存键值
        SharedPreferences.Editor editor = mPreferences.edit();
        for (int i = 0; i < saveValue.length; i++) {
            editor.putString(saveValue[i], mValues.get(i).getKey() + "=" + mValues.get(i).getValue());
        }
        editor.apply();
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.txt_discover:
                LogUtil.w(TAG, "开始搜索");
                imageRotate.setVisibility(View.VISIBLE);
                txtDiscover.setVisibility(View.INVISIBLE);
                if (null == operatingAnim) {
                    operatingAnim = AnimationUtils.loadAnimation(this, R.anim.tip);
                    LinearInterpolator lin = new LinearInterpolator();
                    operatingAnim.setInterpolator(lin);
                }
                imageRotate.setAnimation(operatingAnim);
                bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
                if (null == bluetoothAdapter) {
                    Toast.makeText(this, "您的设备不支持蓝牙", Toast.LENGTH_SHORT).show();
                    return;
                }
                if (!bluetoothAdapter.isEnabled()) {
                    Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                    startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
                    return;
                }
                bluetoothAdapter.startDiscovery();
                dialog.show();
                break;
            case R.id.image_back:
                finish();
                overridePendingTransition(R.anim.push_right_in,
                        R.anim.push_right_out);
                break;
        }
    }

    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
        switch (adapterView.getId()) {
            case R.id.grad_key_value:
                if (null != connectedThread) {
                    connectedThread.sendBuffer(mValues.get(i).getValue().getBytes());
                }
                break;
            case R.id.list_dis:
                dialog.dismiss();
                address = datas.get(i).getKey();
                name = datas.get(i).getValue();
                ConnectThread connectThread = new ConnectThread();
                connectThread.start();
                break;
        }

    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case REQUEST_ENABLE_BT:
                if (resultCode != 0) {
                    dialog.show();
                    bluetoothAdapter.startDiscovery();
                } else {
                    imageRotate.setVisibility(View.INVISIBLE);
                    txtDiscover.setVisibility(View.VISIBLE);
                    imageRotate.clearAnimation();
                    Toast.makeText(this, "请打开蓝牙", Toast.LENGTH_SHORT).show();
                }
                break;
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    @Override
    protected void onDestroy() {
        if (null != receiver)
            unregisterReceiver(receiver);
        super.onDestroy();
    }

    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
        switch (seekBar.getId()) {
            case R.id.seek_p:
                txtSeekP.setText(String.format("%s", progress));
                if (null != connectedThread)
                    connectedThread.sendBuffer(("A0" + progress).getBytes());
                break;
            case R.id.seek_i:
                txtSeekI.setText(String.format("%s", progress));
                if (null != connectedThread)
                    connectedThread.sendBuffer(("A1" + progress).getBytes());
                break;
            case R.id.seek_d:
                txtSeekD.setText(String.format("%s", progress));
                if (null != connectedThread)
                    connectedThread.sendBuffer(("A2" + progress).getBytes());
                break;
        }
    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {

    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {

    }

    @Override
    public boolean onItemLongClick(AdapterView<?> parent, View view, final int position, long id) {
        final EditText editValue, editKey;
        Button btnNo, btnYes;
        if (null == editDialog) {
            editDialog = new ListDialog(this);
            editDialog.setContentView(R.layout.view_set_blue_value);
        }
        editKey = (EditText) editDialog.findViewById(R.id.edit_key);
        editValue = (EditText) editDialog.findViewById(R.id.edit_value);
        btnNo = (Button) editDialog.findViewById(R.id.btn_no);
        btnYes = (Button) editDialog.findViewById(R.id.btn_yes);

        editKey.setText(mValues.get(position).getKey());
        editKey.setSelection(editKey.getText().length());
        editValue.setText(mValues.get(position).getValue());
        btnYes.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mValues.get(position).setKey(editKey.getText().toString());
                mValues.get(position).setValue(editValue.getText().toString());
                mBlueValueAdapter.setmData(mValues);
                mPreferences.edit().putString("key" + (position + 1), editKey.getText().toString() + "=" +
                        editValue.getText().toString()).apply();

                editDialog.dismiss();
            }
        });
        btnNo.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                editDialog.dismiss();
            }
        });

        editDialog.show();
        return false;
    }

    private class BluetoothReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                if (devices.indexOf(device.getName()) == -1) {
                    devices.add(device.getName());
                    datas.add(new BlueValue(device.getName(), device.getAddress()));
                }
                LogUtil.w(TAG, "device:" + device.toString());
                deviceList.add(device);

                //动态添加搜索到得设备到对话框中
                if (null == dataAdapter) {
                    dataAdapter = new CommDataAdapter<BlueValue>(datas, R.layout.view_item_blue) {
                        @Override
                        public void bindView(ViewHolder holder, BlueValue obj) {
                            holder.setText(R.id.txt_blue_name, obj.getKey());
                            holder.setText(R.id.txt_blue_address, obj.getValue());
                        }
                    };
                    listView.setAdapter(dataAdapter);
                } else {
                    dataAdapter.setmData(datas);
                }
                listView.invalidate();
                dialog.invalidateOptionsMenu();

            } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
                if (!(datas.size() > 0)) {
                    Toast.makeText(BlueToothActivity.this, "没有发现周围设备", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(BlueToothActivity.this, "搜索完成", Toast.LENGTH_SHORT).show();
                }
                imageRotate.setVisibility(View.INVISIBLE);
                txtDiscover.setVisibility(View.VISIBLE);
                imageRotate.clearAnimation();
            } else if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
                Toast.makeText(BlueToothActivity.this, "连接成功", Toast.LENGTH_SHORT).show();
                txtConnStatus.setText(String.format("已连接：%s", name));
            } else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
                Toast.makeText(BlueToothActivity.this, "蓝牙已断开连接", Toast.LENGTH_SHORT).show();
                txtConnStatus.setText("未连接");
            }
        }
    }

    private Handler mHandler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message message) {
            switch (message.what) {
                case 0x123:
                    Toast.makeText(BlueToothActivity.this, "套接字创建失败", Toast.LENGTH_SHORT).show();
                    break;
                case 0x124:
                    Toast.makeText(BlueToothActivity.this, "连接异常", Toast.LENGTH_SHORT).show();
                    break;
            }
            return true;
        }
    });

    private class ConnectThread extends Thread {
        private BluetoothSocket mSocket;
        private BluetoothDevice device;

        @Override
        public void run() {
            try {
                device = bluetoothAdapter.getRemoteDevice(address);
                mSocket = device.createRfcommSocketToServiceRecord(UUID.fromString(Common.SPP_UUID));
            } catch (Exception e) {
                mHandler.sendEmptyMessage(0x123);
                e.printStackTrace();
                return;
            }
            try {
                bluetoothAdapter.cancelDiscovery();
                mSocket.connect();
                connectedThread = new ConnectedThread(mSocket);
                connectedThread.start();
            } catch (IOException e) {
                mHandler.sendEmptyMessage(0x123);
                try {
                    mSocket.close();
                    mSocket = null;
                } catch (IOException e2) {
                    Log.e(TAG, "Cannot close connection when connection failed");
                }
            }
            super.run();
        }
    }

    private static class ConnectedThread extends Thread {
        private BluetoothSocket mSocket;
        private OutputStream mOutputStream;
        private InputStream mInputStream;
        private static boolean isRead = true;

        public ConnectedThread(BluetoothSocket socket) {
            mSocket = socket;
            try {
                mOutputStream = mSocket.getOutputStream();
                mInputStream = mSocket.getInputStream();
                LogUtil.w(TAG, "ConnectedThread");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void run() {
            byte[] buffer = new byte[1024];
            int bytes;
            while (true) {
                try {
                    String s = "";
                    if ((bytes = mInputStream.read(buffer)) > 0) {
                        byte[] buf_data = new byte[bytes];
                        System.arraycopy(buffer, 0, buf_data, 0, bytes);
                        s = new String(buf_data, "utf-8");
                    }
                    LogUtil.w(TAG, "read=" + s);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        public boolean sendBuffer(byte[] mBuffer) {
            boolean result = true;
            String tail = "\r\n";
            byte[] tailBuffer = tail.getBytes();
            byte[] mBufferTemp = new byte[mBuffer.length + tailBuffer.length];
            System.arraycopy(mBuffer, 0, mBufferTemp, 0, mBuffer.length);
            System.arraycopy(tailBuffer, 0, mBufferTemp, mBuffer.length, tailBuffer.length);
            //注意：我得项目中需要在每次发送后面加\r\n，大家根据项目项目做修改，也可以去掉，直接发送mBuffer
            try {
                if (mOutputStream != null) {
                    mOutputStream.write(mBufferTemp);
                } else {
                    result = false;
                }
            } catch (IOException e) {
                e.printStackTrace();
                result = false;
            }
            return result;
        }
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            finish();
            return true;
        } else
            return super.onKeyDown(keyCode, event);
    }
}
